#include <common.h>
#include <fs.h>

#if defined(MULTIPROGRAM) && !defined(TIME_SHARING)
# define MULTIPROGRAM_YIELD() yield()
#else
# define MULTIPROGRAM_YIELD()
#endif

#define NAME(key) \
  [AM_KEY_##key] = #key,

static const char *keyname[256] __attribute__((used)) = {
  [AM_KEY_NONE] = "NONE",
  AM_KEYS(NAME)
};
size_t events_read(void *buf, size_t offset, size_t len)  {

  char cache[64];
  size_t n = 0;//cache remain num
  size_t idx = 0;//cache read index
  // if(n == 0) {
    AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);
    n = sprintf(cache,"k%c %s\n",ev.keydown?'d':'u',keyname[ev.keycode]);
    idx = 0;
    assert(n <= 64&&n!=0);
  // }
  char *p = buf;
  int cnt = 0;
  while (cnt < len&&n > 0)
  {
    p[cnt++] = cache[idx++];
    n--;
  }
  
  return cnt;
  

}
size_t serial_write(const void *buf, size_t offset, size_t len) {
  const char *p = buf;
  for (size_t i = 0; i < len; i++)
  {
    putch(*p++);
  }
  return 0;
}

// size_t events_read(void *buf, size_t offset, size_t len) {
//   int fd = fs_open("/dev/events",0,0);
//   assert(fd != -1);
//   len = fs_read(fd,buf,len);
//   return len;
// }

size_t dispinfo_read(void *buf, size_t offset, size_t len) {
  AM_GPU_CONFIG_T dispinfo = io_read(AM_GPU_CONFIG);
  char cache[64];
  size_t n = 0;//cache remain num
  size_t idx = 0;//cache read index
  n = sprintf(cache,"WIDTH : %d\nHEIGHT:%d\n",dispinfo.width,dispinfo.height);
  
  char *p = buf;
  int cnt = 0;
  while (cnt < len&& idx < n)
  {
    p[cnt++] = cache[idx++];
  }
  
  return cnt;
}

static int fbctl_w,fbctl_h;
size_t fbctl_read(void *buf, size_t offset, size_t len) {
  char cache[64];
  size_t n = 0;//cache remain num
  size_t idx = 0;//cache read index
  n = sprintf(cache,"%d %d",fbctl_w,fbctl_h);
  
  char *p = buf;
  int cnt = 0;
  while (cnt < len&& idx < n)
  {
    p[cnt++] = cache[idx++];
  }
  
  return 0;
}
size_t fbctl_write(const void *buf, size_t offset, size_t len) {
  int h=0,w=0;
  const char *p = buf; 
  size_t cnt = 0;   
  while (cnt < len)
  {
    char c = p[cnt++];
    if(c >= '0' && c <= '9') h = h*10+(c-'0');
    else if(c == '\n' || c == ' ') break;
    else return 0;
  }
  while (cnt < len)
  {
    char c = p[cnt++];
    if(c >= '0' && c <= '9') w = w*10+(c-'0');
    else if(c == '\n' || c == ' ') break;
    else return 0;
  }
  fbctl_h = h;
  fbctl_w = w;
  Log("FB_CTL:write h : %d w : %d",h,w);
  return len;
}


size_t fb_vmemsz;
size_t fb_write(const void *buf, size_t offset, size_t len) {
  AM_GPU_CONFIG_T cfg = io_read(AM_GPU_CONFIG);
  int x = offset/sizeof(uint32_t)%cfg.width;
  int y = offset/sizeof(uint32_t)/cfg.width;
  io_write(AM_GPU_FBDRAW, x, y, (void*)buf, len/sizeof(uint32_t), 1, true);
  return len;

}

void init_device() {
  Log("Initializing devices...");
  ioe_init();
}
